// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UILiveObjectDescriptorLocal.cs" company="Open Trader">
//   Copyright (c) David Denis (david.denis@systemathics.com)
// </copyright>
// <summary>
//   |  Open Trader - The Open Source Systematic Trading Platform
//   |
//   |  This program is free software: you can redistribute it and/or modify
//   |  it under the terms of the GNU General Public License as published by
//   |  the Free Software Foundation, either version 2 of the License, or
//   |  (at your option) any later version.
//   |
//   |  This program is distributed in the hope that it will be useful,
//   |  but WITHOUT ANY WARRANTY; without even the implied warranty of
//   |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   |  GNU General Public License for more details.
//   |
//   |  You should have received a copy of the GNU General Public License
//   |  along with this program.  If not, see http://www.gnu.org/licenses
//   |
//   |  Up to date informations about Open Trader can be found at :
//   |    http://opentrader.org
//   |    http://opentrader.codeplex.com
//   |
//   |  For professional services, please visit us at :
//   |    http://www.systemathics.com
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Org.OpenTrader.Framework.UI.Forms
{
    #region Using Directives

    using System;
    using System.Data;
    using System.Windows.Forms;

    using Org.OpenTrader.Framework.Entities;
    using Org.OpenTrader.Framework.LiveObjects;
    using Org.OpenTrader.Framework.LiveObjects.Interfaces;

    #endregion

    /// <summary>
    /// The ui live object descriptor local.
    /// </summary>
    public partial class UILiveObjectDescriptorLocal : UIControl
    {
        #region Constants and Fields

        /// <summary>
        /// The containersCache.
        /// </summary>
        private readonly LiveObjectContainerCache containersCache;

        /// <summary>
        /// The interface.
        /// </summary>
        private readonly string iface;

        /// <summary>
        /// The liveObject.
        /// </summary>
        private readonly DBLiveObject liveObject;

        /// <summary>
        /// The port.
        /// </summary>
        private readonly int port = 1024 + Rand.NextInt(16000);

        /// <summary>
        /// The type.
        /// </summary>
        private readonly string type;

        /// <summary>
        /// The container.
        /// </summary>
        private ILiveObjectContainer container;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="UILiveObjectDescriptorLocal"/> class.
        /// </summary>
        public UILiveObjectDescriptorLocal()
        {
            this.InitializeComponent();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="UILiveObjectDescriptorLocal"/> class.
        /// </summary>
        /// <param name="type">
        /// The type.
        /// </param>
        /// <param name="iface">
        /// The iface.
        /// </param>
        /// <param name="liveObject">
        /// The liveObject.
        /// </param>
        /// <param name="containersCache">
        /// The containersCache.
        /// </param>
        public UILiveObjectDescriptorLocal(
            string type, 
            /* "A" , "S", "P" */
            string iface, 
            DBLiveObject liveObject, 
            LiveObjectContainerCache containersCache)
        {
            this.InitializeComponent();

            this.type = type;
            this.liveObject = liveObject;
            this.iface = iface;
            this.containersCache = containersCache;

            // containers = containers;

            // Setup combobox containers
            this.comboboxContainers.Items.Clear();
            this.comboboxContainers.Items.AddRange(this.containersCache.Containers);
            this.comboboxClasses.Enabled = false;

            // Try to load the container
            if (this.liveObject.EntityState != EntityState.Detached)
            {
                this.liveObject.DBContainerReference.Load();
            }

            // If a container was chosen before, use it to start
            if (this.liveObject.DBContainer != null)
            {
                this.comboboxContainers.SelectedItem = this.containersCache.GetContainer(this.liveObject.DBContainer.ID);
                if (this.liveObject.ClassFullTypeName != null)
                {
                    this.comboboxClasses.SelectedItem = this.liveObject.ClassFullTypeName;
                    if (this.liveObject.ListenURL != null)
                    {
                        this.textboxUrl.Text = this.liveObject.ListenURL;
                        this.textboxUrl.Enabled = true;
                        this.checkboxListen.Enabled = true;
                        this.checkboxListen.Checked = true;
                    }
                    else
                    {
                        this.ChooseToListenOrNot();
                    }
                }
                else
                {
                    this.ChooseClass();
                }
            }
            else
            {
                // No container present, choose
                this.ChooseContainer();
            }
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets CurrentContainer.
        /// </summary>
        public ILiveObjectContainer CurrentContainer
        {
            get
            {
                if (this.comboboxContainers.SelectedIndex >= 0)
                {
                    return this.comboboxContainers.SelectedItem as ILiveObjectContainer;
                }

                return null;
            }
        }

        /// <summary>
        /// Gets a value indicating whether SelectedListening.
        /// </summary>
        public bool SelectedListening
        {
            get
            {
                return this.checkboxListen.Checked;
            }
        }

        /// <summary>
        /// Gets SelectedListenURL.
        /// </summary>
        public string SelectedListenURL
        {
            get
            {
                var url = this.textboxUrl.Text;
                if (url == string.Empty)
                {
                    url = null;
                }

                return this.SelectedListening ? url : null;
            }
        }

        /// <summary>
        /// Gets SelectedPort.
        /// </summary>
        public int SelectedPort
        {
            get
            {
                return this.port;
            }
        }

        /// <summary>
        /// Gets SelectedTypeName.
        /// </summary>
        public string SelectedTypeName
        {
            get
            {
                if (this.comboboxClasses.SelectedIndex >= 0)
                {
                    return this.comboboxClasses.SelectedItem as string;
                }

                return null;
            }
        }

        /// <summary>
        /// Gets SelectedTypeNameAttributes.
        /// </summary>
        public Attribute[] SelectedTypeNameAttributes
        {
            get
            {
                if (this.SelectedTypeName != null)
                {
                    return this.container.GetAttributes(this.SelectedTypeName);
                }

                return null;
            }
        }

        /// <summary>
        /// Gets SelectedTypeNameImplementedInterfaceName.
        /// </summary>
        public string[] SelectedTypeNameImplementedInterfaceName
        {
            get
            {
                return this.container.GetImplementedInterfaces(this.SelectedTypeName);
            }
        }

        /// <summary>
        /// Gets SelectedTypeShortName.
        /// </summary>
        public string SelectedTypeShortName
        {
            get
            {
                return this.SelectedTypeName.Substring(this.SelectedTypeName.LastIndexOf('.') + 1);
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// The choose class.
        /// </summary>
        private void ChooseClass()
        {
            this.buttonApply.Enabled = false;

            if (this.CurrentContainer != null)
            {
                this.checkboxListen.Enabled = false;
                this.checkboxListen.Checked = false;
                this.textboxUrl.Text = null;
                this.textboxUrl.Enabled = false;
                this.comboboxClasses.Enabled = true;
                this.comboboxClasses.Items.Clear();

                this.container = this.CurrentContainer;

                // All the implementors of interface are ...
                if (this.container != null)
                {
                    var implementors = this.container.GetImplementors(this.iface);
                    this.comboboxClasses.Items.AddRange(implementors);
                }
                else
                {
                    return;
                }
            }
            else
            {
                this.ChooseContainer();
            }
        }

        /// <summary>
        /// The choose container.
        /// </summary>
        private void ChooseContainer()
        {
            this.buttonApply.Enabled = false;

            this.container = null;
            this.textboxUrl.Enabled = false;
            this.textboxUrl.Lines = new string[] { };
        }

        /// <summary>
        /// The choose to listen or not.
        /// </summary>
        private void ChooseToListenOrNot()
        {
            if (this.type == "S")
            {
                if (this.SelectedTypeName != null)
                {
                    this.checkboxListen.Enabled = true;
                    this.textboxInterface.Text = string.Join(";", this.SelectedTypeNameImplementedInterfaceName);
                }
                else
                {
                    this.checkboxListen.Enabled = false;
                    this.textboxInterface.Text = null;
                }
            }
            else
            {
                this.checkboxListen.Enabled = false;
                this.textboxInterface.Text = null;
            }
        }

        /// <summary>
        /// The checkboxListen_ checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void OnCheckboxListenCheckedChanged(object sender, EventArgs e)
        {
            var b = sender as CheckBox;
            this.textboxUrl.Enabled = this.checkboxListen.Checked;
            if (this.SelectedListening)
            {
                this.textboxUrl.Lines = new[]
                    {
                        string.Format("remoting://0.0.0.0:{0}/{1}", this.SelectedPort, this.SelectedTypeShortName) 
                    };
            }
            else
            {
                this.textboxUrl.Enabled = false;
                this.textboxUrl.Lines = new string[] { };
            }
        }

        /// <summary>
        /// The comboboxClasses_ selected index changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void OnComboboxClassesSelectedIndexChanged(object sender, EventArgs e)
        {
            this.buttonApply.Enabled = true;

            this.ChooseToListenOrNot();
        }

        /// <summary>
        /// The comboboxContainers_ selected index changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void OnComboboxContainersSelectedIndexChanged(object sender, EventArgs e)
        {
            this.ChooseClass();
        }

        /// <summary>
        /// The buttonApply_ click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void OnNuttonApplyClick(object sender, EventArgs e)
        {
            if (this.comboboxClasses.SelectedIndex >= 0)
            {
                // Set fields on the given object
                this.liveObject.Location = "L";
                this.liveObject.DBContainer = DBContainerHelpers.GetContainer(this.CurrentContainer.Descriptor.ID);
                this.liveObject.ClassFullTypeName = this.SelectedTypeName;
                this.liveObject.ListenURL = this.SelectedListenURL;
                this.liveObject.URL = null;

                var container = this.containersCache.GetContainer(this.liveObject.DBContainer.ID);
                var configuration = DBConfigurationHelpers.LoadConfiguration(
                    this.liveObject.DBConfigurationID, this.liveObject.ClassFullTypeName, container);
                DBConfigurationHelpers.SaveConfiguration(configuration);

                if (this.ContainingForm != null)
                {
                    this.ContainingForm.Destroy();
                }
            }
        }

        #endregion
    }
}